package com.smartlink.app.face;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ProgressDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

import com.iflytek.cloud.ErrorCode;
import com.iflytek.cloud.FaceRequest;
import com.iflytek.cloud.RequestListener;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechUtility;
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.AsyncHttpResponseHandler;
import com.smartlink.app.R;
import com.smartlink.app.common.Constant;
import com.smartlink.app.dialog.WaitDialog;

import org.apache.http.Header;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class OnlineFaceDemo extends Activity implements OnClickListener {
    private final int REQUEST_PICTURE_CHOOSE = 1;
    private final int REQUEST_CAMERA_IMAGE = 2;
    private static final String TAG = "OnlineFaceDemo";
    String failPath = "";

    private Bitmap mImage = null;
    private byte[] mImageData = null;
    // authid为6-18个字符长度，用于唯一标识用户
    private String mAuthid = null;
    private Toast mToast;
    // 进度对话框
    private ProgressDialog mProDialog;
    // 拍照得到的照片文件
    private File mPictureFile;
    // FaceRequest对象，集成了人脸识别的各种功能
    private FaceRequest mFaceRequest;
    private Button btn_change_bluetooth;
    private Button btn_verify;
    private BluetoothAdapter adapter;
    private SharedPreferences sp;
    private ImageView iv_sign_back;
    private WaitDialog waitDialog;

    @SuppressLint("ShowToast")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_online_demo);
        // 在程序入口处传入appid，初始化SDK
        SpeechUtility.createUtility(this, "appid=" + getString(R.string.app_id));
        sp = getSharedPreferences("main", MODE_PRIVATE);
        //获取蓝牙适配器
        adapter = BluetoothAdapter.getDefaultAdapter();
        //广播接收过滤
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
        intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
        intentFilter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
        intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
        intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        // 注册广播接收器，接收并处理搜索结果
        registerReceiver(receiver, intentFilter);
        // 寻找蓝牙设备，android会将查找到的设备以广播形式发出去
        adapter.startDiscovery();
        //显示加载对话框
        waitDialog = WaitDialog.getWaitDialog(this);


        btn_change_bluetooth = (Button) findViewById(R.id.btn_change_bluetooth);
        btn_change_bluetooth.setText("重新搜索");
        btn_change_bluetooth.setEnabled(false);
        btn_verify = (Button) findViewById(R.id.btn_verify);
        iv_sign_back = (ImageView) findViewById(R.id.iv_sign_back);


        btn_change_bluetooth.setOnClickListener(this);
        btn_verify.setOnClickListener(this);
        btn_verify.setEnabled(false);
        iv_sign_back.setOnClickListener(this);

        mToast = Toast.makeText(this, "", Toast.LENGTH_SHORT);

        mProDialog = new ProgressDialog(this);
        mProDialog.setCancelable(true);
        mProDialog.setTitle("请稍后");

        mProDialog.setOnCancelListener(new OnCancelListener() {

            @Override
            public void onCancel(DialogInterface dialog) {
                // cancel进度框时,取消正在进行的操作
                if (null != mFaceRequest) {
                    mFaceRequest.cancel();
                }
            }
        });

        mFaceRequest = new FaceRequest(this);
    }

    private void register(JSONObject obj) throws JSONException {
        int ret = obj.getInt("ret");
        if (ret != 0) {
            showTip("注册失败");
            return;
        }
        if ("success".equals(obj.get("rst"))) {
            showTip("注册成功");
        } else {
            showTip("注册失败");
        }
    }

    private void verify(JSONObject obj) throws JSONException {
        int ret = obj.getInt("ret");
        if (ret != 0) {
            showTip("验证失败");
            return;
        }
        if ("success".equals(obj.get("rst"))) {
            if (obj.getBoolean("verf")) {
                String studentNubmer = sp.getString("number", "");
                String ip = sp.getString("ip", Constant.HTTP.HTTP_PORT);
                String classroomId = sp.getString("classRoomId", "");
                //认证成功,请求服务器
                String path = "http://" + ip + ":8080/smartlink/signIn?number=" + studentNubmer + "&classroomId=" + classroomId;
                AsyncHttpClient asyncHttpClient = new AsyncHttpClient();
                asyncHttpClient.get(path, new AsyncHttpResponseHandler() {
                    @Override
                    public void onSuccess(int i, Header[] headers, byte[] bytes) {
                        SharedPreferences.Editor edit = sp.edit();
                        //保存签到状态为：已签到
                        edit.putString("studentState", "已签到");
                        showTip("通过验证，签到成功！");
                        OnlineFaceDemo.this.finish();
                    }

                    @Override
                    public void onFailure(int i, Header[] headers, byte[] bytes, Throwable throwable) {
                        Toast.makeText(OnlineFaceDemo.this, "签到失败", Toast.LENGTH_SHORT).show();
                    }
                });
            } else {
                //签到失败
                showTip("验证未通过，签到失败");
            }
        } else {
            showTip("验证失败");
        }
    }

    private void detect(JSONObject obj) throws JSONException {
        int ret = obj.getInt("ret");
        if (ret != 0) {
            showTip("检测失败");
            return;
        }

        if ("success".equals(obj.get("rst"))) {
            JSONArray faceArray = obj.getJSONArray("face");

            Paint paint = new Paint();
            paint.setColor(Color.RED);
            paint.setStrokeWidth(Math.max(mImage.getWidth(), mImage.getHeight()) / 100f);

            Bitmap bitmap = Bitmap.createBitmap(mImage.getWidth(),
                    mImage.getHeight(), Config.ARGB_8888);
            Canvas canvas = new Canvas(bitmap);
            canvas.drawBitmap(mImage, new Matrix(), null);
            for (int i = 0; i < faceArray.length(); i++) {
                float x1 = (float) faceArray.getJSONObject(i)
                        .getJSONObject("position").getDouble("left");
                float y1 = (float) faceArray.getJSONObject(i)
                        .getJSONObject("position").getDouble("top");
                float x2 = (float) faceArray.getJSONObject(i)
                        .getJSONObject("position").getDouble("right");
                float y2 = (float) faceArray.getJSONObject(i)
                        .getJSONObject("position").getDouble("bottom");
                paint.setStyle(Style.STROKE);
                canvas.drawRect(new Rect((int) x1, (int) y1, (int) x2, (int) y2),
                        paint);
            }
            mImage = bitmap;
            ((ImageView) findViewById(R.id.online_img)).setImageBitmap(mImage);
        } else {
            showTip("检测失败");
        }
    }

    @SuppressWarnings("rawtypes")
    private void align(JSONObject obj) throws JSONException {
        int ret = obj.getInt("ret");
        if (ret != 0) {
            showTip("聚焦失败");
            return;
        }
        if ("success".equals(obj.get("rst"))) {
            Paint paint = new Paint();
            paint.setColor(Color.BLUE);
            paint.setStrokeWidth(Math.max(mImage.getWidth(), mImage.getHeight()) / 100f);

            Bitmap bitmap = Bitmap.createBitmap(mImage.getWidth(),
                    mImage.getHeight(), Config.ARGB_8888);
            Canvas canvas = new Canvas(bitmap);
            canvas.drawBitmap(mImage, new Matrix(), null);

            JSONArray faceArray = obj.getJSONArray("result");
            for (int i = 0; i < faceArray.length(); i++) {
                JSONObject landmark = faceArray.getJSONObject(i).getJSONObject(
                        "landmark");
                Iterator it = landmark.keys();
                while (it.hasNext()) {
                    String key = (String) it.next();
                    JSONObject postion = landmark.getJSONObject(key);
                    canvas.drawPoint((float) postion.getDouble("x"),
                            (float) postion.getDouble("y"), paint);
                }
            }

            mImage = bitmap;
            ((ImageView) findViewById(R.id.online_img)).setImageBitmap(mImage);
        } else {
            showTip("聚焦失败");
        }
    }

    private RequestListener mRequestListener = new RequestListener() {

        @Override
        public void onEvent(int eventType, Bundle params) {
        }

        @Override
        public void onBufferReceived(byte[] buffer) {
            if (null != mProDialog) {
                mProDialog.dismiss();
            }

            try {
                String result = new String(buffer, "utf-8");
                Log.d("FaceDemo", result);

                JSONObject object = new JSONObject(result);
                String type = object.optString("sst");
                if ("reg".equals(type)) {
                    register(object);
                } else if ("verify".equals(type)) {
                    verify(object);
                } else if ("detect".equals(type)) {
                    detect(object);
                } else if ("align".equals(type)) {
                    align(object);
                }
            } catch (UnsupportedEncodingException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (JSONException e) {
                // TODO: handle exception
            }
        }

        @Override
        public void onCompleted(SpeechError error) {
            if (null != mProDialog) {
                mProDialog.dismiss();
            }

            if (error != null) {
                switch (error.getErrorCode()) {
                    case ErrorCode.MSP_ERROR_ALREADY_EXIST:
                        showTip("authid已经被注册，请更换后再试");
                        break;

                    default:
                        showTip(error.getPlainDescription(true));
                        break;
                }
            }
        }
    };

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_change_bluetooth:
                //重新搜索蓝牙
                researchBluetooth();
                break;
            case R.id.btn_verify:
                //验证
                //启动人脸识别拍照功能
                Intent intentPhotograph = new Intent(this, VideoDemo.class);
                intentPhotograph.putExtra("startType", 1);
                startActivityForResult(intentPhotograph, 2);
                break;
            case R.id.iv_sign_back:
                //返回点击
                //关闭当前Activity
                finish();
                break;
        }
    }

    private void researchBluetooth() {
        adapter.startDiscovery();
        btn_change_bluetooth.setEnabled(false);
        if (waitDialog != null) {
            waitDialog.show();
        } else {
            waitDialog = WaitDialog.getWaitDialog(this);
            waitDialog.show();
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // 如果返回码是人脸验证
        if (resultCode == VideoDemo.FACE_VERIFY_RESULT) {
            //获取人脸照片
            failPath = data.getStringExtra("file");
            Log.i(TAG, "onActivityResult: >>>>>>>>>>" + failPath);
            FaceUtil.cropPicture(this, Uri.fromFile(new File(failPath)));
        } else {
            if (resultCode != RESULT_OK) {
                return;
            }
            String fileSrc = null;
            if (requestCode == REQUEST_PICTURE_CHOOSE) {
                if ("file".equals(data.getData().getScheme())) {
                    // 有些低版本机型返回的Uri模式为file
                    fileSrc = data.getData().getPath();
                } else {
                    // Uri模型为content
                    String[] proj = {MediaStore.Images.Media.DATA};
                    Cursor cursor = getContentResolver().query(data.getData(), proj,
                            null, null, null);
                    cursor.moveToFirst();
                    int idx = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                    fileSrc = cursor.getString(idx);
                    cursor.close();
                }
                // 跳转到图片裁剪页面
                FaceUtil.cropPicture(this, Uri.fromFile(new File(fileSrc)));
            } else if (requestCode == REQUEST_CAMERA_IMAGE) {
                if (null == mPictureFile) {
                    showTip("拍照失败，请重试");
                    return;
                }
                fileSrc = mPictureFile.getAbsolutePath();
                updateGallery(fileSrc);
                // 跳转到图片裁剪页面
                FaceUtil.cropPicture(this, Uri.fromFile(new File(fileSrc)));
            } else if (requestCode == FaceUtil.REQUEST_CROP_IMAGE) {//剪切图片返回
                // 获取返回数据
                Bitmap bmp = data.getParcelableExtra("data");

                // 若返回数据不为null，保存至本地，防止裁剪时未能正常保存
                if (null != bmp) {
                    FaceUtil.saveBitmapToFile(OnlineFaceDemo.this, bmp);
                }
                // 获取图片保存路径
                fileSrc = FaceUtil.getImagePath(OnlineFaceDemo.this);
                // 获取图片的宽和高
                Options options = new Options();
                options.inJustDecodeBounds = true;
                mImage = BitmapFactory.decodeFile(fileSrc, options);

                // 压缩图片
                options.inSampleSize = Math.max(1, (int) Math.ceil(Math.max(
                        (double) options.outWidth / 1024f,
                        (double) options.outHeight / 1024f)));
                options.inJustDecodeBounds = false;
                mImage = BitmapFactory.decodeFile(fileSrc, options);


                // 若mImageBitmap为空则图片信息不能正常获取
                if (null == mImage) {
                    showTip("图片信息无法正常获取！");
                    return;
                }

                // 部分手机会对图片做旋转，这里检测旋转角度
                int degree = FaceUtil.readPictureDegree(fileSrc);
                if (degree != 0) {
                    // 把图片旋转为正的方向
                    mImage = FaceUtil.rotateImage(degree, mImage);
                }

                ByteArrayOutputStream baos = new ByteArrayOutputStream();

                //可根据流量及网络状况对图片进行压缩
                mImage.compress(Bitmap.CompressFormat.JPEG, 80, baos);
                mImageData = baos.toByteArray();
                ((ImageView) findViewById(R.id.online_img)).setImageBitmap(mImage);
                //照片回显成功，暂停3秒 进行验证
                try {
                    Thread.sleep(3000);
                    //获取登录的学号，设为面识别id
                    mAuthid = sp.getString("number", "");
                    //mAuthid = ((EditText)findViewById(R.id.et_sid)).getText().toString();
                    if (TextUtils.isEmpty(mAuthid)) {
                        return;
                    }

                    if (null != mImageData) {
                        mProDialog.setMessage("验证中...");
                        mProDialog.show();
                        // 设置用户标识，格式为6-18个字符（由字母、数字、下划线组成，不得以数字开头，不能包含空格）。
                        // 当不设置时，云端将使用用户设备的设备ID来标识终端用户。
                        mFaceRequest.setParameter(SpeechConstant.AUTH_ID, mAuthid);
                        mFaceRequest.setParameter(SpeechConstant.WFR_SST, "verify");
                        mFaceRequest.sendRequest(mImageData, mRequestListener);
                    } else {
                        showTip("请选择图片后再验证");
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    @Override
    public void finish() {
        if (null != mProDialog) {
            mProDialog.dismiss();
        }
        super.finish();
    }

    private void updateGallery(String filename) {
        MediaScannerConnection.scanFile(this, new String[]{filename}, null,
                new MediaScannerConnection.OnScanCompletedListener() {

                    @Override
                    public void onScanCompleted(String path, Uri uri) {

                    }
                });
    }

    private void showTip(final String str) {
        mToast.setText(str);
        mToast.show();
    }


    private List<String> bluetoothAddress = new ArrayList<>();
    private BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            //搜索到了蓝牙设备
            if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                bluetoothAddress.add(device.getAddress());

            }
            //扫描完成
            if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {

                System.out.println(bluetoothAddress.size());
                //E0:19:1D:69:CD:A4
                //       5s
                SharedPreferences sharedPreferences = getSharedPreferences("main", MODE_PRIVATE);
                String bluetooth = sharedPreferences.getString("bluetooth", "78:9F:70:BF:1A:31");
                btn_change_bluetooth.setEnabled(true);
                //如果存在指定的蓝牙
                if (bluetoothAddress.contains(bluetooth)) {
                    Toast.makeText(OnlineFaceDemo.this, "已找到签到信号，请点击签到", Toast.LENGTH_SHORT).show();
                    btn_verify.setEnabled(true);
                } else {
                    Toast.makeText(OnlineFaceDemo.this, "未搜索到指定的蓝牙", Toast.LENGTH_SHORT).show();
                }
                //清空扫描到的蓝牙设备
                bluetoothAddress.clear();

                waitDialog.dismiss();
            }
            if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {

                if (adapter.isEnabled()) {
                    // 寻找蓝牙设备，android会将查找到的设备以广播形式发出去
                    adapter.startDiscovery();
                } else {
                    btn_verify.setEnabled(false);
                }
            }
        }
    };

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //注销广播接收者
        if (receiver != null) {
            unregisterReceiver(receiver);
        }

    }
}
